package com.labot.util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

public class StringUtils {
	
	/**
	 * Si es demasiado largo lo trunca y le agrega "..."
	 * @param s
	 * @param length
	 * @return
	 */
	public static String cutString(String s, Integer length) {
		if(s == null){
			return "";
		}
		if(s.length()<=length){
			return s;
		}
		if(s.length()>length){
			return s.substring(0,length-3) + "...";
		}
		return s;
	}
	
	public static String fixString(String s, Integer length) {
		String blancos = "";
		for (int i = 0; i < length; i++) {
			blancos = blancos.concat(" ");
		}
		if (s==null)
			return blancos;
		if (s.length()==0)
			return blancos;
		if (s.length()==length)
			return s;
		if (s.length()>length)
			return s.substring(0,length);
		return (blancos + s).substring(s.length());
	}
	
	/**
	 * Camel Case
	 * 
	 * Parametro de entrada EJ: ENRIQUE BARBEITO
	 * Salida: Enrique Barbeito
	 * @param s
	 * @return
	 */
	public static  String toCamelCase(String s){
		   if (s==null) {
			   return "";
		   }
		   if (s.equals("")){
			   return "";
		   }
		   if (s.length()<2){
			   return s.toUpperCase();
		   }
		   s = removeExcesiveSpaces(s);
		   s = s.trim();
		   String[] parts = s.split(" ");
		   String camelCaseString = "";
		   for (String part : parts){
		      camelCaseString = camelCaseString +" "+ toProperCase(part);
		   }
		   return camelCaseString.trim();
		}

	public static  String toProperCase(String s) {
		    return s.substring(0, 1).toUpperCase() +
		               s.substring(1).toLowerCase();
		}

	public static String removeExcesiveSpaces(String string) {
		if (string == null) {
			return string;
		}
		if (string.length() < 1) {
			return string;
		}
		string = string.replaceAll("[ ]{2,}", " ");
		return string;
	}
	
	/**
	 * Devuelve solo los numeros de una cadena de caracteres.
	 * @param string
	 * @return
	 */
	public static String getOnlyNumbers(String string) {
		if (string == null) {
			return string;
		}
		if (string.length() < 1) {
			return string;
		}
		string = string.replaceAll("[^\\d]", "");
		return string;
	}

	/**
	 * A un string largo, sin saltos de lineas lo formatea para que entre en
	 * "columns" de ancho
	 * @param string
	 * @param columns
	 * @return
	 */
	public static String addNewLines(String string, Integer columns) {
		String[] palabras = string.split(" "); // separo por espacios.
		Integer columnsAcumuladas = columns;
		String resultado = "";
		for (String palabra : palabras) {
			resultado = resultado.concat(palabra);
			//Si se llega al final de la linea poner un enter, sino un espacio.
			if (resultado.length() > columnsAcumuladas) {
				resultado = resultado.concat("\n");
				columnsAcumuladas = columnsAcumuladas + columns;
			} else {
				resultado = resultado.concat(" ");				
			}
		}
		
		return resultado;
	}
	
	private static int minimum(int a, int b, int c) {
        return Math.min(Math.min(a, b), c);
	}

	/**
	 * Devuelve las diferencias entre el string 1 y 2
	 * EJ: Mattioli vs Matioli resultado: 1
	 *     Perez vs Peres      resultado: 1
	 * @param str1
	 * @param str2
	 * @return
	 */
	public static int computeLevenshteinDistance(CharSequence str1,
                CharSequence str2) {
        int[][] distance = new int[str1.length() + 1][str2.length() + 1];

        for (int i = 0; i <= str1.length(); i++)
                distance[i][0] = i;
        for (int j = 1; j <= str2.length(); j++)
                distance[0][j] = j;

        for (int i = 1; i <= str1.length(); i++)
                for (int j = 1; j <= str2.length(); j++)
                        distance[i][j] = minimum(
                                        distance[i - 1][j] + 1,
                                        distance[i][j - 1] + 1,
                                        distance[i - 1][j - 1]
                                                        + ((str1.charAt(i - 1) == str2.charAt(j - 1)) ? 0
                                                                        : 1));

        return distance[str1.length()][str2.length()];
	}
	
	public static Boolean elMenorEstaIncluidoEnMayor(String a, String b) {
		a = removeExcesiveSpaces(a);
		b = removeExcesiveSpaces(b);
		if (a.length()<b.length()){
			String temp = b;
			b = a;
			a = temp;
		}
		String[] arrayA = a.split(" ");
		String[] arrayB = b.split(" ");
		Boolean isOk = true;

		//A es mas grande, hay que hacer: los elementos de B estan contenidos en A??
		for (int i = 0; i < arrayB.length; i++) {
			Boolean estaIncluido = false;
			String bTemp = arrayB[i];
			for (int j = 0; j < arrayA.length; j++) {
				String aTemp = arrayA[j];
				if (aTemp.equals(bTemp)){
					estaIncluido = true;
				}
			}
			if (!estaIncluido) {
				isOk = false; 
			}
		}

		return isOk;
	}
	
	public static Boolean isFechaParecida(Date a, Date b) throws Exception {
		String fecha1 = DateUtil.dateToString(a, DateUtil.SQL_FECHA);
		String fecha2 = DateUtil.dateToString(b, DateUtil.SQL_FECHA);
		return isNombreParecido(fecha1, fecha2, false);
		
	}
	
	public static Boolean isNombreParecido(String a, String b, Boolean exacto) throws Exception {
		//Todo a mayusculas
		a = a.toUpperCase();
		b = b.toUpperCase();
		//Quitar espacios de m�s entre palabras.
		a = removeExcesiveSpaces(a);
		b = removeExcesiveSpaces(b);
		a = a.replaceAll(" . ", " ");
		b = b.replaceAll(" . ", " ");
		a = a.replaceAll(" .\\. ", " ");
		b = b.replaceAll(" .\\. ", " ");
		
		/**
		 * Ej:
		 * BARBEITO ENRIQUE
		 * BARBEITO ENRIQUE GABRIEL
		 * 
		 * Como uno esta contenido en el otro sale por true;
		 */
		if(elMenorEstaIncluidoEnMayor(a,b)){
			return true;
		}
		String[] arrayA = a.split(" ");
		String[] arrayB = b.split(" ");
		/**
		 * En arrayA debo tener el que tiene menos palabras...
		 */
		if (arrayA.length > arrayB.length){
			String[] temp = arrayB;
			arrayB = arrayA;
			arrayA = temp;
		}
		List<String> listA = Arrays.asList(arrayA);
		Collections.sort(listA);
		
		List<String> listB = Arrays.asList(arrayB);
		Collections.sort(listB);
		
		for (String palabra : listA) {
			Boolean estaContenidoEnListaB = false;
			for (String palabra2 : listB) {
				if (exacto) {
					if (palabra.equals(palabra2)) {
						estaContenidoEnListaB = true;
					}
				} else {					
					if (isPalabraSimilar(palabra, palabra2)){
						estaContenidoEnListaB = true;
					}
				}
			}
			if (!estaContenidoEnListaB) {
				return false;
			}
		}
		return true;
	}
	
	
	
	public static Boolean isPalabraSimilar(String a, String b) throws Exception {
		//Probamos por similitud. Si el logaritmo de Levenshtein es menor a 2 significa que es parecido.
		
		Integer levenshtein = computeLevenshteinDistance(a, b);
		if (a.length() <= 10) {			
			if (levenshtein <= 2) {
				return true;
			}
		} else if (a.length() > 10 && a.length() <= 20) {
			if (levenshtein <= 4) {
				return true;
			}
		} else if (a.length() > 20) {
			if (levenshtein <= 6) {
				return true;
			}
		}
		return false;
	}
	
	/** 
	 * Genera las claves
	 * @param digitos
	 * @return
	 */
	public static String generarRandomInteger(Integer digitos) {
		String n = "";
		int d;
		for (int i = 0; i < digitos; i++) {
			d = (int) (Math.random() * 10);// Genera numeros de 0 al 9
			n += d;// Concatena digito por digito
		}
		return n;
	}
	
	public static String removeInvalidChars(String p){
		
	       List <String> invalidChars = new ArrayList<String>();
	       
	       invalidChars.add("/");
	       invalidChars.add("?");
	       invalidChars.add("<");
	       invalidChars.add(">");
	       invalidChars.add("\\");
	       invalidChars.add(":");
	       invalidChars.add("|");
	       invalidChars.add("\"");
	       invalidChars.add("*");
	       
	       for (String str : invalidChars) {
	    	   p = p.replace(str, "");
//	      	   System.out.println(p);
	       	   
		} 
		return p;
	}
	
	public static String getTest(String a, String b, String c) {
		return a+b+c;
	}
	
	public static String concatList(List<String> lista, String separator){
		
		String cadena = null;
		boolean first = true;
		Iterator<String> iter = lista.iterator();
		while(iter.hasNext() ){
			if (first) {
				cadena = (String) iter.next();	
				first = false;
			} else {				
				cadena = cadena + separator + (String) iter.next();	
			}
				
		}
				
		return cadena;
	}
	
}
